﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Linq.Expressions;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using UdpPeer.Assets;
using UdpPeer.Protocols;

namespace UdpPeer.ViewModels
{
    /// <summary>
    /// 主要处理逻辑
    /// </summary>
    public class MainWindowModel : NotifyPropertyBase
    {

        private CommandInput udpClientConnectionAct = new CommandInput();

        /// <summary>
        /// UDP客户端联接功能动作.
        /// </summary>
        public CommandInput UdpClientConnectionAct
        {
            get { return udpClientConnectionAct; }

        }

        private string _IP = "127.0.0.1";
        /// <summary>
        /// IP
        /// </summary>
        public string IP
        {
            get { return _IP; }
            set
            {
                _IP = value;
                //使用lamda表达式获取属性名
                this.PropertyChangedRegist(p => p.IP);
            }
        }

        private int _Port = 23356;
        /// <summary>
        /// 端口
        /// </summary>
        public int Port
        {
            get { return _Port; }
            set
            {
                _Port = value;
                this.PropertyChangedRegist(p => p.Port);
            }
        }

        private string _Status = "正在..";
        /// <summary>
        /// 状态信息
        /// </summary>
        public string Status
        {
            get { return _Status; }
            set
            {
                _Status = value;
                this.PropertyChangedRegist(p => p.Status);
            }
        }

        private string _SendText = "";
        /// <summary>
        /// 发送字符串
        /// </summary>
        public string SendText
        {
            get { return _SendText; }
            set
            {
                _SendText = value;
                this.PropertyChangedRegist(p => p.SendText);
            }
        }
        /// <summary>
        /// 接收字符串
        /// </summary>
        private string _RecText = "";
        /// <summary>
        /// 接收字符串
        /// </summary>
        public string RecText
        {
            get { return _RecText; }
            set
            {
                _RecText = value;
                this.PropertyChangedRegist(p => p.RecText);
            }
        }

        private CommandInput sendCmd = new CommandInput();
        /// <summary>
        /// 发送指令
        /// </summary>
        public CommandInput SendCmd
        {
            get { return sendCmd; }
        }

        private CommandInput selectRowCmd = new CommandInput();
        /// <summary>
        /// 发送指令
        /// </summary>
        public CommandInput SelectRowCmd
        {
            get { return selectRowCmd; }
        }

        private Ents _SendEndPoint = null;
        /// <summary>
        /// 发送目标节点
        /// </summary>
        public Ents SendEndPoint
        {
            get { return _SendEndPoint; }
            set
            {
                _SendEndPoint = value;
                this.PropertyChangedRegist(p => p.SendEndPoint);
            }
        }

        private Ents _当前公网节点信息 = null;

        public Ents 当前公网节点信息
        {
            get { return _当前公网节点信息; }
            set
            {
                _当前公网节点信息 = value;
                this.PropertyChangedRegist(p => p.当前公网节点信息);
            }
        }
        /// <summary>
        /// 握手状态信息
        /// </summary>
        private string _StatusHandClasp = string.Empty;
        /// <summary>
        /// 握手状态信息
        /// </summary>
        public string StatusHandClasp
        {
            get { return _StatusHandClasp; }
            set { _StatusHandClasp = value;
            this.PropertyChangedRegist(p => p.StatusHandClasp);
            }
        }


        private System.Collections.ObjectModel.ObservableCollection<Ents> _Nodes = new System.Collections.ObjectModel.ObservableCollection<Ents>();
        /// <summary>
        /// 节点信息
        /// </summary>
        public System.Collections.ObjectModel.ObservableCollection<Ents> Nodes
        {
            get { return _Nodes; }
            set
            {
                _Nodes = value;
                this.PropertyChangedRegist(p => p.Nodes);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        public System.Windows.Threading.Dispatcher Dispatcher { get; set; }

        /// <summary>
        /// 远程调度服务器节点
        /// </summary>
        internal Ents DispatcherServer { get; set; }


        #region 处理方法联接终端

        public UdpPeerNode node = new UdpPeerNode();
        /// <summary>
        /// 节点模式
        /// </summary>
        /// <param name="parameter"></param>
        public void ConnExecute(object parameter)
        {
            if ((node.IsRuning)) { Status = "已经正在运行了。。"; return; }
            try
            {
                var ep = new System.Net.IPEndPoint(System.Net.IPAddress.Parse(IP), Port);
                node.ReceiveHandler = (data, cp) =>
                {
                    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
                    var txt = System.Text.Encoding.UTF8.GetString(data);
                    var peerCp = new Ents() { 名称 = "Peer", 是否连接 = true, 节点 = cp };
                    //接收数据
                    foreach (string strs in MessagePackegHelper.Instance.GetReceiveProtocolString(txt))
                    {

                        IProtocol msg = MessagePackegHelper.Instance.GetEntity<IProtocol>(strs);
                        //////////------------------------------------------------------------------------//////////------------------------------------------------------------------------
                        switch (msg.消息类型)
                        {
                            case MessageType.点对点请求:


                                var pp = msg as 点对点请求;

                                if (当前公网节点信息 != null)
                                {
                                    //发前是请求目标节点，A向B发起请求。B向A发指令打洞
                                    if (当前公网节点信息.节点字符串 == pp.请求目标节点.节点字符串)
                                    {
                                        //向A发指令打洞
                                        ServerNode.Send(
                                                System.Text.Encoding.UTF8.GetBytes(
                                                MessagePackegHelper.Instance.GetSendProtocolString(new NAT握手协议()
                                                {
                                                    握手发起节点 = 当前公网节点信息,
                                                    握手目标节点 = pp.发起请求节点
                                                }
                                                )),
                                        pp.发起请求节点.节点);
                                    }
                                }
                                System.Threading.Tasks.Task.Factory.StartNew(() =>
                                {
                                    System.Threading.Thread.Sleep(50);
                                    //////////--------------向服务器发送向A打洞指令----------------------------------------------------------
                                    ServerNode.Send(
                                            System.Text.Encoding.UTF8.GetBytes(
                                                MessagePackegHelper.Instance.GetSendProtocolString(new 点对点请求()
                                                {
                                                    发起请求节点 = 当前公网节点信息,
                                                    请求目标节点 = pp.发起请求节点,
                                                }
                                                )),
                                            DispatcherServer.节点);
                                });
                                
                                break;
                            case MessageType.NAT握手协议:
                                var vv = msg as NAT握手协议;
                                Dispatcher.Invoke(new Action(() =>
                                {
                                    Status = msg.消息类型 + " 发起：" + vv.握手发起节点.节点字符串;
                                    StatusHandClasp = msg.消息类型 + " 已经接收 发起：" + vv.握手发起节点.节点字符串;
                                }));

                                break;
                            case MessageType.联接调度服务器:
                                var dd = msg as 联接调度服务器;

                                Dispatcher.Invoke(new Action(() =>
                                {
                                    当前公网节点信息 = dd.节点的公网信息;
                                }));
                                break;
                            case MessageType.一般数据信息:

                                break;
                            case MessageType.节点列表:
                                var lst = msg as 节点列表;
                                ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
                                bool needadd = false;
                                //如果节点不包含则需要添加
                                var eps = Nodes.Select(p => p.节点);
                                if (!eps.Contains(cp))
                                {
                                    needadd = true;
                                }
                                List<Ents> others = new List<Ents>();
                                //服务器节点返回数据,清单数据
                                if (((IPEndPoint)cp).Address.ToString() == IP && ((IPEndPoint)cp).Port == Port)
                                {
                                    others = lst.列表;
                                }

                                Dispatcher.Invoke(new Action(() =>
                                {

                                    if (needadd)
                                    {
                                        Nodes.Add(new Ents() { 名称 = "Peer", 是否连接 = false, 节点 = cp });
                                    }
                                    //添加清单返回的列表
                                    foreach (var item in others)
                                    {
                                        if (!eps.Contains(item.节点))
                                        {
                                            Nodes.Add(item);
                                        }
                                    }
                                }));
                                break;
                        }

                        Dispatcher.Invoke(new Action(() =>
                        {
                            Status = "接收到节点：" + cp + " " + msg.消息类型.ToString();
                            RecText = "节点：" + cp + " " + txt;
                        }));
                    }

                };
                node.StatusHandler = (txt) =>
                {
                    System.Windows.Threading.Dispatcher.CurrentDispatcher.Invoke(new Action(() =>
                    {
                        Status = txt;
                    }))
    ;
                };
                //--------------------
                if (node.Connection(ep))
                {
                    //设置调度服务器节点
                    DispatcherServer = SendEndPoint = new Ents() { 名称 = "调度服务端", 是否连接 = true, 节点 = new System.Net.IPEndPoint(System.Net.IPAddress.Parse(IP), Port) };
                    Dispatcher.Invoke(new Action(() =>
                    {
                        Nodes.Add(DispatcherServer);
                    }));
                    node.Start();


                    node.Client.SendTo(System.Text.Encoding.UTF8.GetBytes(MessagePackegHelper.Instance.GetSendProtocolString(new 联接调度服务器())), DispatcherServer.节点);

                }
            }
            catch (Exception ex) { Status = ex.ToString(); }
        }
        //发送数据
        public void SendData(object parameter)
        {
            if (node.IsRuning)
            {
                //节点是否有远程节点
                if (SendEndPoint == null)
                {
                    SendEndPoint = new Ents() { 节点 = new System.Net.IPEndPoint(System.Net.IPAddress.Parse(IP), Port) };
                }
                //发送数据
                var sendbytes = System.Text.Encoding.UTF8.GetBytes(
                    MessagePackegHelper.Instance.GetSendProtocolString(new 一般数据信息()
                    {
                        Text = SendText
                    })
                    );
                if (SendEndPoint == DispatcherServer)
                {
                    node.Client.SendTo(sendbytes, SendEndPoint.节点);
                }
                else
                {
                    node.Send(sendbytes, SendEndPoint.节点);
                }
                Dispatcher.Invoke(new Action(() =>
                {
                    SendEndPoint.是否连接 = true;
                }));
            }
        }
        /// <summary>
        /// 选择发生改变
        /// </summary>
        /// <param name="obj"></param>
        public void RowSelect(object obj)
        {
            if (obj != null)
            {
                if (obj is Array)
                {

                    var arr = (obj as Array);
                    if (arr.Length > 0)
                    {
                        bool islist = false;
                        foreach (var item in arr)
                        {
                            if (item != null && item is Ents)
                            {
                                islist = true;
                                break;
                            }
                        }
                        if (islist)
                        {
                            IList<Ents> ents = arr.Cast<Ents>().ToList();
                            if (ents.Count > 0)
                            {
                                SendEndPoint = ents[0];
                            }
                        }
                    }

                }
            }


        }
        #endregion

        #region 调度服务器
        private int _DisPort = 23356;

        public int DisPort
        {
            get { return _DisPort; }
            set
            {
                _DisPort = value;
                this.PropertyChangedRegist(p => p.DisPort);
            }
        }

        private CommandInput _开始 = new CommandInput();

        public CommandInput 开始
        {
            get { return _开始; }
            set
            {
                _开始 = value;
                this.PropertyChangedRegist(p => p.开始);
            }
        }


        private System.Collections.ObjectModel.ObservableCollection<Ents> _PeerNodes = new System.Collections.ObjectModel.ObservableCollection<Ents>();

        public System.Collections.ObjectModel.ObservableCollection<Ents> PeerNodes
        {
            get { return _PeerNodes; }
            set
            {
                _PeerNodes = value;
                this.PropertyChangedRegist(p => p.PeerNodes);
            }
        }


        public UdpPeerNode ServerNode = new UdpPeerNode();
        /// <summary>
        /// 服务端模式
        /// </summary>
        /// <param name="parameter"></param>
        public void 开始Execute(object parameter)
        {
            var ep = new System.Net.IPEndPoint(System.Net.IPAddress.Any, DisPort);
            ServerNode.CreateServer(ep);
            ServerNode.IsRuning = true;
            Status = "调试服务器模式，邦定：" + ep;
            //---------------------------------------------
            ServerNode.ReceiveHandler = (data, cp) =>
            {

                var txt = System.Text.Encoding.UTF8.GetString(data);
                var peerCp = new Ents() { 名称 = "Peer", 是否连接 = true, 节点 = cp };
                //接收数据
                foreach (string strs in MessagePackegHelper.Instance.GetReceiveProtocolString(txt))
                {

                    IProtocol msg = MessagePackegHelper.Instance.GetEntity<IProtocol>(strs);

                    switch (msg.消息类型)
                    {
                        case MessageType.点对点请求:
                            var pp = msg as 点对点请求;
                            ServerNode.Send(
                                System.Text.Encoding.UTF8.GetBytes(
                                MessagePackegHelper.Instance.GetSendProtocolString(msg)
                                ), pp.请求目标节点.节点);
 
                            break;
                        case MessageType.联接调度服务器:
                            var ss =
                                MessagePackegHelper.Instance.GetSendProtocolString(new 联接调度服务器()
                                {
                                    节点的公网信息 = peerCp
                                }
                                );
                            ServerNode.Send(System.Text.Encoding.UTF8.GetBytes(ss), cp);
                            //发送列表
                            SendPeerNodes();
                            break;
                        case MessageType.一般数据信息:
                            var ac = msg as 一般数据信息;
                            if (!string.IsNullOrEmpty(ac.Text))
                            {
                                if (ac.Text.IndexOf("list") != -1 || ac.Text.IndexOf("列表") != -1)
                                {
                                    //发送列表
                                    SendPeerNodes();
                                }
                            }
                            break;
                    }

                    Dispatcher.Invoke(new Action(() =>
                    {
                        Status = "接收到节点：" + cp + " " + msg.消息类型.ToString();
                    }));
                }
                bool needadd = false;
                //如果节点不包含则需要添加
                if (!PeerNodes.Select(p => p.节点).Contains(cp))
                {
                    needadd = true;
                }

                Dispatcher.Invoke(new Action(() =>
                {



                    RecText = "节点：" + cp + " " + txt;
                    if (needadd)
                    {
                        PeerNodes.Add(peerCp);
                    }

                }));

            };
            ServerNode.StatusHandler = (txt) =>
            {
                System.Windows.Threading.Dispatcher.CurrentDispatcher.Invoke(new Action(() =>
                {
                    Status = txt;
                }))
;
            };
        }
        #endregion

        /// <summary>
        /// 发送节点列表
        /// </summary>
        protected void SendPeerNodes()
        {
            //节点列表
            byte[] todatas = System.Text.Encoding.UTF8.GetBytes(
                MessagePackegHelper.Instance.GetSendProtocolString(new 节点列表()
                {
                    列表 = PeerNodes.ToList()
                })
                );
            //广播数据节点：
            foreach (var key in ServerNode.ClientConnections)
            {
                ServerNode.Send(todatas, key.Value);
            }
        }


        #region 自动发送
        private bool autoSend = false;

        public bool AutoSend
        {
            get { return autoSend; }
            set
            {
                autoSend = value;
                this.PropertyChangedRegist(p => p.AutoSend);

                if (autoSend)
                {

                    timer.Start();
                }
                else
                {
                    timer.Stop();
                }

            }
        }
        private int _SendInv = 1000;
        /// <summary>
        ///   发送间隔
        /// </summary>
        public int SendInterval
        {
            get { return _SendInv; }
            set
            {
                _SendInv = value;
                this.PropertyChangedRegist(p => p.SendInterval);

                autoSend = false;
                timer.Interval = TimeSpan.FromMilliseconds(SendInterval);
                autoSend = true;

            }
        }
        /// <summary>
        /// 构造函数
        /// </summary>
        public MainWindowModel()
        {
            UdpClientConnectionAct.ExecuteAction = ConnExecute;
            SendCmd.ExecuteAction = SendData;
            SelectRowCmd.ExecuteAction = RowSelect;

            开始.ExecuteAction = 开始Execute;
            //Nodes.Add(new Ents() { 名称 = "1212", 是否连接 = false, 节点 = new System.Net.IPEndPoint(System.Net.IPAddress.Parse("192.168.1.31"), 6768) });
            //Nodes.Add(new Ents() { 名称 = "saadf", 是否连接 = false, 节点 = new System.Net.IPEndPoint(System.Net.IPAddress.Parse("192.168.1.32"), 16789) });
            timer.Interval = TimeSpan.FromMilliseconds(SendInterval);
            timer.Tick += timer_Tick;

        }

        void timer_Tick(object sender, EventArgs e)
        {
            //发送数据
            SendData(null);
        }

        protected System.Windows.Threading.DispatcherTimer timer = new System.Windows.Threading.DispatcherTimer();

        #endregion


    }

    public class Ents
    {
        public string 名称 { get; set; }
        internal System.Net.EndPoint 节点 { get; set; }
        /// <summary>
        /// 
        /// </summary>
        public bool 是否连接 { get; set; }

        public string 节点字符串
        {

            get
            {
                return 节点 == null ? string.Empty : 节点.ToString();
            }
            set
            {
                string epstr = value.ToString();
                System.Net.IPEndPoint ep;
                try
                {
                    var arr = epstr.Split(':');
                    节点 = new IPEndPoint(IPAddress.Parse(arr[0]), int.Parse(arr[1]));
                }
                catch
                {
                    节点 = new IPEndPoint(IPAddress.IPv6Any, 0);
                }

            }
        }
    }
}
